#include<iostream>
#include<string>
#include<unistd.h>
using namespace std;
#include<vector>
#include"task.hpp"
#include<sys/wait.h>
class Channel
{
public:
    Channel(int w,pid_t i)
    {
        wfd = w;
        id = i;
    }
    pid_t getid()
    {
        return id;
    }
    int getwfd()
    {
        return wfd;
    }
    void closewfd()
    {
        close(wfd);
    }

private:
    int wfd;
    pid_t id;
};
void work(int rfd)
{
    while(1)
    {
        int command = 0;
        int n = read(rfd, &command, sizeof(command));
        if (n == sizeof(int))
        {
            exec(command);
        }
        else
        {
            close(rfd);
            break;
        }
    }
}
void createChannel(int num,vector<Channel>* v)
{

    for (int i = 0; i < num; i++)
    {
        int pipefd[2] = {0};
        int n = pipe(pipefd);
        if (n < 0)
            exit(2);
        pid_t id = fork();
        if(id==0)
        {
            for(auto i:*v)
            {
                i.closewfd();
            }
            close(pipefd[1]);
            work(pipefd[0]);
            exit(0);
        }        
        close(pipefd[0]);
        v->emplace_back(Channel(pipefd[1], id));
    }
   
}
void sendTask(Channel ch,int task)
{
    write(ch.getwfd(),&task,sizeof(task));
}
int main(int argc,char* argv[])
{
    if(argc!=2)
    {
        cerr << "number error!" << endl;
        return 1;
    }
    vector<Channel> channels;
    int now = 0;
    loadTask();
    int num = std::stoi(argv[1]);
    //1.创建子进程和通信
    createChannel(num, &channels);

    //2.通过channel发放任务
    int cnt = 4;
    while (cnt--)
    {
        int task = selectTask();
        cout << channels[now].getid() << ' ' << task << ':' << endl;
        sendTask(channels[now], task);
        now++;
        now %= num;
        sleep(1);
    }
    // 3.回收管道和子进程
    for(auto &i:channels)
    {
        i.closewfd();
        int status;
        int pid=0;
        pid = waitpid(i.getid(), &status, 0);
        if(pid<0)
            cerr << "error!" << endl;
    }
    return 0;
}